# $LastChangedDate: 2012-10-25 21:35:57 -0400 (Thu, 25 Oct 2012) $
# LEGAL: COPYRIGHT (C) 2010 JIM E. BROOKS WWW.PALOMINO3D.ORG
# Determine C/C++ compiler args.
# C_CXX_FLAGS : C and C++ compiler args.
# C_FLAGS     : C only args.
# CXX_FLAGS   : C++ only args.
# Notes:
# - See module.txt.
#-------------------------------------------------------------------------------

#-------------------------------------------------------------------------------
# Determine which kind of compiler and appropriate compiler args.
#
# Quoting is necessary for compiler args:
# SET( C_CXX_FLAGS "${C_CXX_FLAGS} -Wall -Wunused " )  # right  ## NOTE TRAILING SPACE ##
# SET( C_CXX_FLAGS ${C_CXX_FLAGS} -Wall -Wunused )     # wrong  ## TO SEPARATE COMPILER ARGS ##

IF( CMAKE_COMPILER_IS_GNUCXX OR ($ENV{CXX} MATCHES "clang") )  # GNU C++ or clang++

    SET( GCC_DEBUG_LEVEL "-g" )
    IF( "${DEBUG}" MATCHES "2" OR DEBUGGER )
        SET( GCC_DEBUG_LEVEL "-g3" )
    ENDIF()

    # Optimization level.
    # [2009/12] Don't use -O3 which is known to compile bad code that causes graphical artifacts.
    # Override cmake trying to use -O3.
    # BTW, any optimization args in the env vars CFLAGS/CXXFLAGS will affect cmake.
    SET(   CMAKE_C_FLAGS_RELEASE        "-DNDEBUG -O2 "    CACHE STRING "Compiler args for Release."        FORCE )
    SET( CMAKE_CXX_FLAGS_RELEASE        "-DNDEBUG -O2 "    CACHE STRING "Compiler args for Release."        FORCE )
    SET(   CMAKE_C_FLAGS_MINSIZEREL     "-DNDEBUG -Os "    CACHE STRING "Compiler args for MinSizeRel."     FORCE )
    SET( CMAKE_CXX_FLAGS_MINSIZEREL     "-DNDEBUG -Os "    CACHE STRING "Compiler args for MinSizeRel."     FORCE )
    SET(   CMAKE_C_FLAGS_RELWITHDEBINFO "-DNDEBUG -O2 ${GCC_DEBUG_LEVEL} " CACHE STRING "Compiler args for RelWithDebInfo." FORCE )
    SET( CMAKE_CXX_FLAGS_RELWITHDEBINFO "-DNDEBUG -O2 ${GCC_DEBUG_LEVEL} " CACHE STRING "Compiler args for RelWithDebInfo." FORCE )

    # Prevent compiler producing bad code from a cast.
    SET( C_CXX_FLAGS "${C_CXX_FLAGS} -fno-strict-aliasing " )

    # Warnings:
    # These cause too many warnings in system headers: -Wshadow (but -Wshadow is very important)
    # -Wuninitialized is appropriately enabled by -Wall
    SET( C_CXX_FLAGS "${C_CXX_FLAGS} -Wall -Wunused -Wshadow " )
    SET(   CXX_FLAGS "${CXX_FLAGS} -Wold-style-cast " )  # C++ only
   #SET(   CXX_FLAGS "${CXX_FLAGS} -Woverloaded-virtual " )  # C++ only (excessive warnings)
   #SET(   CXX_FLAGS "${C_CXX_FLAGS} -Wconversion " )  # C++ only (excessive warnings)

    # Optimize/release args:
    IF( PROJECT_BUILD_TYPE MATCHES "Release" )
        # Optimize:
       #SET( C_CXX_FLAGS "${C_CXX_FLAGS} -fsingle-precision-constant " )
        IF( NOT APPLE )  # Apple gcc 4.0 malfunctions
            SET( C_CXX_FLAGS "${C_CXX_FLAGS} -ffast-math -fno-finite-math-only " )
        ENDIF()

        # Strip symbols for all Release builds except ReleaseSym.
        # cmake won't pass -s to gcc for MinSizeRel.
        IF( NOT PROJECT_BUILD_TYPE MATCHES "ReleaseSym" )
            # KLUDGE: Apple executables must have symbols or loader will fail.
            IF( APPLE )
                MESSAGE( STATUS "(Apple: must not strip symbols in executable)" )
                SET( PROJECT_BUILD_TYPE_EXTRA_MSG "(keeping symbols) ${PROJECT_BUILD_TYPE_EXTRA_MSG}" )
            ELSE()
                # Pass -s to strip symbols.
                SET( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s " )
            ENDIF()
        ENDIF()
    ENDIF()

    # Debug args:
    IF( NOT GCC_DEBUG_OPT_FLAG )  # project-specific
        #SET( GCC_DEBUG_OPT_FLAG "-O" )  # gdb can't determine values/args if -O is used
        SET( GCC_DEBUG_OPT_FLAG "-O0" )  # can omit trailing space
    ENDIF()
    IF( PROJECT_BUILD_TYPE MATCHES "DebugMin" )  # ORDER-DEPENDENT
        # No debug symbols.
        # The reason is that executable would be huge on Apple Mac.
        SET( C_CXX_FLAGS "${C_CXX_FLAGS} -g0 ${GCC_DEBUG_OPT_FLAG} " )
    ELSEIF( PROJECT_BUILD_TYPE MATCHES "Debug" )
        # Debug:
        SET( C_CXX_FLAGS "${C_CXX_FLAGS} ${GCC_DEBUG_LEVEL} ${GCC_DEBUG_OPT_FLAG} " )
    ENDIF()

    # Profiling args:
    IF( PROJECT_BUILD_TYPE MATCHES "ProfileNoOpt" )
        SET( C_CXX_FLAGS "${C_CXX_FLAGS} -pg -O0 " )
    ELSEIF( PROJECT_BUILD_TYPE MATCHES "ProfileOpt" )
        SET( C_CXX_FLAGS "${C_CXX_FLAGS} -pg -O2 " )
    ENDIF()

ELSEIF(MSVC)  # Visual C++

    SET( C_CXX_FLAGS "${C_CXX_FLAGS} /O2 /G6 /W2 " )

ENDIF()

#-------------------------------------------------------------------------------
# OS specific compiler/linker args.

IF( UNIX )
    ADD_DEFINITIONS( -DOS_UNIX=1 )

    IF( CMAKE_SYSTEM_NAME MATCHES "Linux" )
        ADD_DEFINITIONS( -DOS_LINUX=1 )
    ELSEIF( CMAKE_SYSTEM_NAME MATCHES "FreeBSD" )
        ADD_DEFINITIONS( -DOS_FREEBSD=1 )
        IF( PROJECT_BUILD_TYPE MATCHES "Debug" )
            SET( SYSTEM_LIBS ${SYSTEM_LIBS} kvm )  # for MemoryUsed() in FreeBSD
        ENDIF()
    ELSEIF( APPLE )
        ADD_DEFINITIONS( -DOS_APPLE=1 )
        SET( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -framework CoreServices " )
        SET( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -framework Carbon " )
        SET( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -framework Cocoa " )
        SET( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -framework AGL " )
        SET( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -framework OpenGL " )
        # Tell GCC where other system include directories are.
        # Also should suppress warnings in system headers.
        SET( C_CXX_FLAGS "${C_CXX_FLAGS} -isystem /usr/local/include -isystem /opt/local/include " )
    ENDIF()

    # Link with pthread explicitly (for any UNIX besides FreeBSD).
    # Mixing FreeBSD's different thread libs will cause startup to fail.
    SET( SYSTEM_LIBS ${SYSTEM_LIBS} pthread )
ELSEIF( WIN32 )
    ADD_DEFINITIONS( -DOS_WINDOWS=1 )
    ADD_DEFINITIONS( -D_SCL_SECURE_NO_WARNINGS )
    ADD_DEFINITIONS( -D_CRT_SECURE_NO_DEPRECATE )
    # Enable assert() by passing DEBUG=1 to C++ compiler.
    ADD_DEFINITIONS( -DDEBUG=1 )
    # winmm for joystick, comctl32 for FLTK.
    SET( SYSTEM_LIBS ${SYSTEM_LIBS} winmm comctl32 )
ENDIF()

#-------------------------------------------------------------------------------

# Final step: Apply C/C++ args to cmake.
# C_CXX_FLAGS are common to both C and C++.
SET( CMAKE_C_FLAGS   "${CMAKE_C_FLAGS} ${C_FLAGS} ${C_CXX_FLAGS} " )      # C
SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_FLAGS} ${C_CXX_FLAGS} " )  # C++
